package cn.lili.event.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.cache.Cache;
import cn.lili.cache.CachePrefix;
import cn.lili.common.enums.PromotionTypeEnum;
import cn.lili.common.security.enums.SceneEnums;
import cn.lili.common.utils.SnowFlake;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.event.TradeEvent;
import cn.lili.exchange.AmqpExchangeProperties;
import cn.lili.modules.goods.client.GoodsSkuClient;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.enums.GoodsTypeEnum;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.vo.CartVO;
import cn.lili.modules.order.order.client.OrderClient;
import cn.lili.modules.order.order.client.OrderItemClient;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.dto.OrderSearchParams;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.enums.*;
import cn.lili.modules.order.trade.client.OrderLogClient;
import cn.lili.modules.order.trade.entity.dos.OrderLog;
import cn.lili.modules.payment.client.WalletPointClient;
import cn.lili.modules.payment.entity.dto.UserPointUpdateDTO;
import cn.lili.modules.payment.entity.enums.UserPointServiceEnum;
import cn.lili.modules.promotion.client.MemberCouponClient;
import cn.lili.modules.promotion.client.PromotionsClient;
import cn.lili.modules.promotion.entity.dos.FullDiscount;
import cn.lili.routing.OrderRoutingKey;
import cn.lili.util.AmqpMessage;
import cn.lili.util.AmqpSender;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 订单状态处理类
 *
 * @author Chopper
 * @since 2020-07-03 11:20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FullDiscountExecute implements TradeEvent, OrderStatusChangeEvent {

    private final Cache cache;

    private final OrderClient orderClient;

    private final OrderItemClient orderItemClient;

    private final OrderLogClient orderLogClient;

    private final MemberCouponClient memberCouponClient;

    private final GoodsSkuClient goodsSkuClient;

    private final PromotionsClient promotionsClient;

    private final WalletPointClient walletPointClient;

    private final AmqpSender amqpSender;

    private final AmqpExchangeProperties amqpExchangeProperties;

    @Override
    public void tradeCreate(TradeDTO tradeDTO) {

        tradeDTO.getCartList().forEach(cartVO -> {
            // 有满减优惠，则记录信息
            if ((cartVO.getGiftList() != null && !cartVO.getGiftList().isEmpty()) || (cartVO.getGiftPoint() != null && cartVO.getGiftPoint() > 0) || (cartVO.getGiftCouponList() != null && !cartVO.getGiftCouponList().isEmpty())) {
                cache.put(CachePrefix.ORDER.getPrefix() + cartVO.getSn(), JSONUtil.toJsonStr(cartVO));
            }
        });
    }

    @Override
    public void orderChange(OrderMessage orderMessage) {
        //如果订单已支付
        if (orderMessage.getNewStatus().equals(OrderStatusEnum.PAID)) {
            log.debug("满减活动，订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
            renderGift(JSONUtil.toBean(cache.getString(CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn()), CartVO.class), orderMessage);
        } else if (orderMessage.getNewStatus().equals(OrderStatusEnum.CANCELLED)) {
            log.debug("满减活动，取消订单状态操作 {}", CachePrefix.ORDER.getPrefix() + orderMessage.getOrderSn());
            OrderSearchParams searchParams = new OrderSearchParams();
            searchParams.setParentOrderSn(orderMessage.getOrderSn());
            searchParams.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
            List<Order> orders = orderClient.queryListByParams(searchParams);
            if (orders != null && !orders.isEmpty()) {
                orderClient.systemCancel(orders.get(0).getSn(), "主订单取消，赠送订单字段自动取消");
            }
            Order order = orderClient.getBySn(orderMessage.getOrderSn());
            if (order.getPayStatus().equals(PayStatusEnum.PAID.name())) {
                this.cancelReturnFullDiscount(order.getSn(), order.getBuyerId());
            }

        }
    }

    private void cancelReturnFullDiscount(String orderSn, String userId) {
        List<OrderItem> orderItems = orderItemClient.getByOrderSn(orderSn);
        if (orderItems != null && !orderItems.isEmpty()) {
            Optional<OrderItem> first = orderItems.stream().filter(i -> PromotionTypeEnum.FULL_DISCOUNT.name().equals(i.getPromotionType())).findFirst();
            if (first.isPresent()) {
                OrderItem orderItem = first.get();
                FullDiscount fullDiscount = promotionsClient.getFullDiscount(orderItem.getPromotionId());
                if (fullDiscount != null) {
                    //如果是赠送优惠券
                    if (Boolean.TRUE.equals(fullDiscount.getPointFlag())) {
                        String content = "订单取消，满赠积分退还：" + fullDiscount.getPoints() + "分";
                        //赠送用户积分
                        walletPointClient.updateMemberPoint(
                                UserPointUpdateDTO.builder()
                                        .userId(userId)
                                        .points(Double.valueOf(fullDiscount.getPoints()))
                                        .userPointServiceEnum(UserPointServiceEnum.RETURN)
                                        .description(content).build());
                    }
                    if (Boolean.TRUE.equals(fullDiscount.getCouponFlag())) {
                        //赠送优惠券
                        memberCouponClient.expireInvalidMemberCoupon(userId, fullDiscount.getCouponId());
                    }
                }
            }
        }
    }

    /**
     * 渲染优惠券信息
     */
    private void renderGift(CartVO cartVO, OrderMessage orderMessage) {
        // 没有优惠信息则跳过
        if (cartVO == null) {
            return;
        }
        Order order = orderClient.getBySn(orderMessage.getOrderSn());
        // 赠送积分判定
        try {
            if (cartVO.getGiftPoint() != null && cartVO.getGiftPoint() > 0) {
                walletPointClient.updateMemberPoint(UserPointUpdateDTO.builder()
                        .userId(order.getBuyerId())
                        .points(cartVO.getGiftPoint())
                        .userPointServiceEnum(UserPointServiceEnum.FULL_DISCOUNT_GIFT)
                        .description("订单满优惠，赠送" + cartVO.getGiftPoint() + "积分").build());
            }
        } catch (Exception e) {
            log.error("订单赠送积分异常", e);
        }

        try {
            // 优惠券判定
            if (cartVO.getGiftCouponList() != null && !cartVO.getGiftCouponList().isEmpty()) {
                cartVO.getGiftCouponList().forEach(couponId -> memberCouponClient.receiveCoupon(couponId, order.getBuyerId(),
                        order.getNickname()));
            }
        } catch (Exception e) {
            log.error("订单赠送优惠券异常", e);
        }

        try {
            // 赠品潘迪ing
            if (cartVO.getGiftList() != null && !cartVO.getGiftList().isEmpty()) {
                generatorGiftOrder(cartVO.getGiftList(), order);
            }
        } catch (Exception e) {
            log.error("订单赠送赠品异常", e);
        }
    }

    /**
     * 生成赠品订单
     *
     * @param skuIds      赠品sku信息
     * @param originOrder 赠品原订单信息
     */
    private void generatorGiftOrder(List<String> skuIds, Order originOrder) {
        //获取赠品列表
        List<GoodsSku> goodsSkus = goodsSkuClient.getGoodsSkuByIdFromCache(skuIds);

        //赠品判定
        if (goodsSkus == null || goodsSkus.isEmpty()) {
            log.error("赠品不存在：{}", skuIds);
            return;
        }

        //赠品分类，分为实体商品/虚拟商品/电子卡券
        List<GoodsSku> physicalSkus =
                goodsSkus.stream().filter(goodsSku -> goodsSku.getGoodsType().equals(GoodsTypeEnum.PHYSICAL_GOODS.name())).collect(Collectors.toList());
        List<GoodsSku> virtualSkus =
                goodsSkus.stream().filter(goodsSku -> goodsSku.getGoodsType().equals(GoodsTypeEnum.VIRTUAL_GOODS.name())).collect(Collectors.toList());

        //如果赠品不为空，则生成对应的赠品订单

        if (!physicalSkus.isEmpty()) {
            giftOrderHandler(physicalSkus, originOrder);
        }
        if (!virtualSkus.isEmpty()) {
            giftOrderHandler(virtualSkus, originOrder);
        }
    }

    /**
     * 赠品订单处理
     *
     * @param skuList       赠品列表
     * @param originOrder   原始订单
     */
    private void giftOrderHandler(List<GoodsSku> skuList, Order originOrder) {
        //初始化订单对象/订单日志/自订单
        Order order = new Order();
        List<OrderItem> orderItems = new ArrayList<>();
        List<OrderLog> orderLogs = new ArrayList<>();
        //初始化价格详情
        PriceDetailDTO priceDetailDTO = new PriceDetailDTO();
        //复制通用属性
        BeanUtil.copyProperties(originOrder, order, "id");
        BeanUtil.copyProperties(priceDetailDTO, order, "id");
        //生成订单参数
        order.setSn(SnowFlake.createStr("G"));
        order.setParentOrderSn(originOrder.getSn());
        order.setOrderPromotionType(OrderPromotionTypeEnum.GIFT.name());
        order.setOrderStatus(OrderStatusEnum.UNPAID.name());
        order.setPayStatus(PayStatusEnum.PAID.name());
        String goodsType = skuList.get(0).getGoodsType();
        if (CharSequenceUtil.isEmpty(goodsType) || goodsType.equals(GoodsTypeEnum.PHYSICAL_GOODS.name())) {
            order.setOrderType(OrderTypeEnum.NORMAL.name());
        } else {
            order.setOrderType(OrderTypeEnum.VIRTUAL.name());
        }
        order.setNeedReceipt(false);
        order.setPriceDetailDTO(priceDetailDTO);
        order.setClientType(originOrder.getClientType());
        //订单日志
        String message = "赠品订单[" + order.getSn() + "]创建";
        orderLogs.add(new OrderLog(order.getSn(), originOrder.getBuyerId(), SceneEnums.MEMBER.name(), originOrder.getNickname(), message));

        //生成子订单
        for (GoodsSku goodsSku : skuList) {
            OrderItem orderItem = new OrderItem();
            BeanUtil.copyProperties(goodsSku, orderItem, "id");
            BeanUtil.copyProperties(priceDetailDTO, orderItem, "id");
            orderItem.setAfterSaleStatus(OrderItemAfterSaleStatusEnum.NEW.name());
            orderItem.setCommentStatus(CommentStatusEnum.NEW.name());
            orderItem.setComplainStatus(OrderComplaintStatusEnum.NEW.name());
            orderItem.setNum(1);
            orderItem.setOrderSn(order.getSn());
            orderItem.setImage(goodsSku.getThumbnail());
            orderItem.setGoodsName(goodsSku.getGoodsName());
            orderItem.setSkuId(goodsSku.getId());
            orderItem.setCategoryId(goodsSku.getCategoryPath().substring(goodsSku.getCategoryPath().lastIndexOf(",") + 1));
            orderItem.setGoodsPrice(goodsSku.getPrice());
            orderItem.setPriceDetailDTO(priceDetailDTO);
            orderItems.add(orderItem);
        }
        //保存订单
        orderClient.save(order);
        orderItemClient.saveBatch(orderItems);
        orderLogClient.saveBatch(orderLogs);


        //发送订单已付款消息（PS:不在这里处理逻辑是因为期望加交给消费者统一处理库存等等问题）
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setOrderSn(order.getSn());
        orderMessage.setPaymentMethod(order.getPaymentMethod());
        orderMessage.setNewStatus(OrderStatusEnum.PAID);


        amqpSender.send(AmqpMessage.builder().exchange(amqpExchangeProperties.getOrder()).routingKey(OrderRoutingKey.STATUS_CHANGE).message(orderMessage).build());
    }
}
